using System;
using System.Collections.Generic;
using System.Text;
using MindFactorial.LaunchPoint.Common;
using System.Reflection;
using System.Xml;
using System.Security;
using System.Security.Permissions;
using System.Net;
using System.Threading;

namespace MindFactorial.LaunchPoint.Runtime
{
  
    /// <summary>
    /// Represents the base class for all connection providers.  Connection providers
    /// provide a safe and abstract way of communicating with the LaunchPoint server.  Essentally
    /// abstracting the internal details of connecting to the server (whether by web service
    /// tcp or whatever) so that from the standpoint of the application, the API is unaltered
    /// </summary>
    public abstract class RuntimeConnectionProvider : ConnectionProvider
    {
        Xml _configurationInfo = null;



        /// <summary>
        /// loads configuration data and does internal initialization
        /// </summary>
        /// <param name="xml"></param>
        /// <param name="name"></param>
        internal void LoadConfigInfo(Xml xml, string name)
        {
            this._configurationInfo = xml;
            this.Name = name;
           
        }

        /// <summary>
        /// gets the connection information associated with the connection provider
        /// </summary>
        protected Xml ConfigurationInfo
        {
            get
            {
                return _configurationInfo;
            }
        }

        /// <summary>
        /// Called by the framework after all configuration data has been loaded into the provider
        /// the base implementation does nothing but this may be overriden in the subclass to initialize
        /// any state needed.
        /// </summary>
        public virtual void Initialize()
        {

        }

        

        /// <summary>
        /// Calls invoke with reduced web permissions
        /// </summary>
        /// <param name="securityInfo"></param>
        /// <param name="adapterID"></param>
        /// <param name="ruleID"></param>
        /// <param name="session_id"></param>
        /// <param name="arguments"></param>
        internal string CallSecureInvoke(Guid session_id, string securityInfo, string adapterID, string ruleID, string arguments)
        {
            //WebPermission webpermission = new WebPermission(PermissionState.Unrestricted);
            NamedPermissionSet ps = new NamedPermissionSet("tempPermissions", PermissionState.Unrestricted);
            ps.Assert();
            return Invoke(session_id,securityInfo, adapterID, ruleID, arguments);            
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="session_id"></param>
        /// <param name="securityInfo"></param>
        /// <param name="adapterID"></param>
        /// <param name="ruleID"></param>
        /// <param name="arguments"></param>
        /// <param name="ruleCompleted"></param>
        internal void CallSecureInvokeAsync(Guid session_id, string securityInfo, string adapterID, string ruleID, string arguments, AsyncRuleCompletedDelegate ruleCompleted)
        {
            NamedPermissionSet ps = new NamedPermissionSet("tempPermissions", PermissionState.Unrestricted);
            ps.Assert();
            AsyncRuleCompletedDelegate acb = delegate(string result)
            {
                ruleCompleted(result);
            };
            InvokeAsync(session_id, securityInfo, adapterID, ruleID, arguments, acb);   
        }

       

        
        /// <summary>
        /// Invokes the connection provider
        /// </summary>
        /// <param name="session_id"></param>
        /// <param name="securityInfo"></param>
        /// <param name="adapterID"></param>
        /// <param name="ruleID"></param>
        /// <param name="arguments"></param>
        /// <returns></returns>
        protected abstract string Invoke(Guid session_id, string securityInfo, string adapterID, string ruleID, string arguments);

        /// <summary>
        /// Calls the connection provider's Invoke function in an asynchrounous fashion.  This base
        /// implementation may be overriden in a subclass to change or augment the behaviour.  By default
        /// it will call the sub class's Invoke method from  STA background thread.
        /// </summary>
        /// <param name="session_id"></param>
        /// <param name="securityInfo"></param>
        /// <param name="adapterID"></param>
        /// <param name="ruleID"></param>
        /// <param name="arguments"></param>
        /// <param name="acb"></param>
        /// <returns></returns>
        protected virtual void InvokeAsync(Guid session_id, string securityInfo, string adapterID, string ruleID, string arguments, AsyncRuleCompletedDelegate acb)
        {
            Thread asyncthread = new Thread(delegate()
            {
                string result = Invoke(session_id,securityInfo, adapterID, ruleID, arguments);
                acb(result);
            });
            asyncthread.SetApartmentState(ApartmentState.STA);
            asyncthread.IsBackground = true;
            asyncthread.Start(); 
        }

       
        

       
    }
}
